﻿using System;
using System.Windows;
using System.Windows.Controls;

namespace Notoric.Gui.Controls
{
    /// <summary>
    /// Interaction logic for ZoomViewer.xaml
    /// </summary>
    public partial class ZoomViewer : UserControl
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of <see cref="ZoomViewer"/> class.
        /// </summary>
        public ZoomViewer()
        {
            InitializeComponent();
        }

        #endregion

        #region Dependency Properties

        /// <summary>
        /// Identifies the ZoomMin dependency property.
        /// </summary>
        public static readonly DependencyProperty ZoomMinProperty = DependencyProperty.Register(
            "ZoomMin", typeof(double), typeof(ZoomViewer), new PropertyMetadata(80.0));

        /// <summary>
        /// Identifies the ZoomMax dependency property.
        /// </summary>
        public static readonly DependencyProperty ZoomMaxProperty = DependencyProperty.Register(
            "ZoomMax", typeof(double), typeof(ZoomViewer), new PropertyMetadata(200.0));

        /// <summary>
        /// Identifies the Zoom dependency property.
        /// </summary>
        public static readonly DependencyProperty ZoomProperty = DependencyProperty.Register(
            "Zoom", typeof(double), typeof(ZoomViewer), new PropertyMetadata(100.0));

        /// <summary>
        /// Identifies the ZoomIncrement dependency property.
        /// </summary>
        public static readonly DependencyProperty ZoomIncrementProperty = DependencyProperty.Register(
            "ZoomIncrement", typeof(double), typeof(ZoomViewer), new PropertyMetadata(10.0));

        #endregion

        #region Event Handlers

        /// <summary>
        /// Occurs when the data context (presented object) has changed.
        /// </summary>
        /// <remarks>
        /// <b>Operation:</b><br/>
        /// The handler disables all controls if the new data context value is <see langword="null"/>
        /// and enables them once it rebecomes a valid reference.
        /// </remarks>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void parentControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue == null || e.NewValue == DependencyProperty.UnsetValue)
            {
                zoom.IsEnabled = false;
                zoomMinus.IsEnabled = false;
                zoomPlus.IsEnabled = false;
                zoomLabel.IsEnabled = false;
            }
            else
            {
                zoomLabel.IsEnabled = true;
                zoomPlus.IsEnabled = true;
                zoomMinus.IsEnabled = true;
                zoom.IsEnabled = true;
            }
        }

        /// <summary>
        /// Occurs when the user clicks on the Zoom Minus (Zoom Out) button.
        /// </summary>
        /// <remarks>
        /// <para>
        /// <b>Operation:</b><br/>
        /// The ZoomIncrement value is subtracted from the Zoom value and the
        /// result is set as the new zoom slider property (which updates the Zoom value).
        /// If the result of the subtraction is bellow the ZoomMin value, the new value
        /// is set to ZoomMin.
        /// </para>
        /// </remarks>
        /// <param name="sender">Reference to the button</param>
        /// <param name="e">Event data</param>
        private void zoomMinus_Click(object sender, RoutedEventArgs e)
        {
            double newVal = Math.Max(zoom.Value - ZoomIncrement, zoom.Minimum);
            zoom.Value = newVal;
        }

        /// <summary>
        /// Occurs when the user clicks on the Zoom Plus (Zoom In) button.
        /// </summary>
        /// <remarks>
        /// <para>
        /// <b>Operation:</b><br/>
        /// The ZoomIncrement value is added to the Zoom value and the
        /// result is set as the new zoom slider property (which updates the Zoom value).
        /// If the result of the addition is above the ZoomMax value, the new value
        /// is set to ZoomMax.
        /// </para>
        /// </remarks>
        /// <param name="sender">Reference to the button</param>
        /// <param name="e">Event data</param>
        private void zoomPlus_Click(object sender, RoutedEventArgs e)
        {
            double newVal = Math.Min(zoom.Value + ZoomIncrement, zoom.Maximum);
            zoom.Value = newVal;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the actual (initial) zoom.
        /// This is a dependency property.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="System.Double"/>
        /// </para>
        /// <para>
        /// Zoom value in percents (default 100%).
        /// </para>
        /// </value>
        public double Zoom
        {
            get { return (double)GetValue(ZoomProperty); }
            set { SetValue(ZoomProperty, value); }
        }

        /// <summary>
        /// Gets or sets the minimal value that the user can set as the zoom propery.
        /// This is a dependency property.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="System.Double"/>
        /// </para>
        /// <para>
        /// Zoom value in percents (default 80%).
        /// </para>
        /// </value>
        public double ZoomMin
        {
            get { return (double)GetValue(ZoomMinProperty); }
            set { SetValue(ZoomMinProperty, value); }
        }

        /// <summary>
        /// Gets or sets the maximal value that the user can set as the zoom propery.
        /// This is a dependency property.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="System.Double"/>
        /// </para>
        /// <para>
        /// Zoom value in percents (default 200%).
        /// </para>
        /// </value>
        public double ZoomMax
        {
            get { return (double)GetValue(ZoomMaxProperty); }
            set { SetValue(ZoomMaxProperty, value); }
        }

        /// <summary>
        /// Gets or sets the value that will be added / subtracted from the Zoom value when user clicks
        /// the zoom + / -  button.
        /// This is a dependency property.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="System.Double"/>
        /// </para>
        /// <para>
        /// The value (in percents) that is added / subtracted from the <see cref="Zoom"/> value
        /// when the zoom + / - button is clicked (default 10%).
        /// </para>
        /// </value>
        public double ZoomIncrement
        {
            get { return (double)GetValue(ZoomIncrementProperty); }
            set { SetValue(ZoomIncrementProperty, value); }
        }

        #endregion
    }
}
